from odoo import models, _, api, fields
from odoo.exceptions import UserError, ValidationError
import requests
import logging
import json

_logger = logging.getLogger(__name__)


class StockPicking(models.Model):
    _inherit = 'stock.picking'

    s_mes_lock = fields.Boolean(string='是否推送mes')

    def create_api_records(self, e, url):
        self.env['api.records'].create({
            'api_route': url,
            'result_json': e,
            'state': 'fail'
        })

    def button_validate(self):
        res = super(StockPicking, self).button_validate()
        # 执行完成后, 作业类型板材发料 推送到mes
        mes_enabled = self.env['s.api.config_parameter'].search([('s_key', '=', 'mes.enabled')], limit=1).s_value
        if mes_enabled:
            if self.filtered(lambda x: x.picking_type_id.barcode == 'WTT-CB'):
                try:
                    result = self.sudo().send_mes()
                    if result.get('resultCode') != '0000':  # 请求失败
                        self.message_post(body= f"同步mes结果失败: {json.dumps(result)}")
                    else:
                        self.message_post(body=f"同步mes成功")
                        self.s_mes_lock = True
                except Exception as e:
                    self.message_post(body= f"同步mes结果失败：{str(e)}")
        return res

    def top_production(self, production):
        # 最顶层production
        ids = production._get_sources()
        parent_ids = [rec for rec in ids]
        if not parent_ids:
            origin = production
        else:
            production = parent_ids[0]
            while parent_ids:
                production = parent_ids.pop()
                ids = production._get_sources()
                parent_ids = [rec for rec in ids]
            origin = production
        return origin

    def send_mes(self, login_list=[], action=False):
        if action and self.env.user.login not in login_list:
            raise ValidationError(f'当前账户不允许执行推送MES操作，请使用【{",".join(login_list)}】')
        if action and self.picking_type_id.barcode != 'WTT-CB':
            raise ValidationError('当前单据不是发料单不允许推送')

        for record in self:
            sql = """select mrp_production_id from s_mrp_production_stock_picking_rel where stock_picking_id={}""".format(record.id)
            self.env.cr.execute(sql)
            ids = self.env.cr.dictfetchall()
            mrp_list = [mrp['mrp_production_id'] for mrp in ids]
            productions = self.env['mrp.production'].sudo().browse(mrp_list)

            if not productions and record.origin:
                base_mo = record.origin.split(' / ')[0]
                productions = self.env['mrp.production'].sudo().search([('base_mo', '=', base_mo)])

            # 00 针对 领料单只关联了外层工单的情况做优化
            all_productions_ids = productions
            for production in productions:
                all_productions_ids |= production._get_children()
            productions = all_productions_ids
            # 00 stop

            # 01 校验时间节点
            mes_flag_time = self.env['s.api.config_parameter'].search([('s_key', '=', 'mes.flag_date')],limit=1).s_value
            if not mes_flag_time:
                raise ValidationError('未配置时间节点')
            # 02 查询工单
            mtrl_list = []
            sync_info = {'mes_flag_time': mes_flag_time}
            sync_info['productions'] = productions.ids
            if len(productions) == 1:
                # 无内层
                mrp_production_ids = productions.filtered(lambda x: fields.Datetime.to_string(x.create_date) > mes_flag_time)
            elif len(productions) > 1 and not productions.filtered(lambda x: x._get_sources()):
                # 无内层
                mrp_production_ids = productions.filtered(lambda x: fields.Datetime.to_string(x.create_date) > mes_flag_time)
            else:
                # 有内层直接判断
                mrp_production_ids = productions.filtered(lambda x: x.product_id.categ_id.code == 'BCP' and fields.Datetime.to_string(x.create_date) > mes_flag_time)
            if not mrp_production_ids:
                raise ValidationError(f"没有可用工单, {mes_flag_time} 之前的工单同步mes会失败")
            for move in record.move_ids_without_package:
                mtrl_list.append({
                    "wp_code": "CUT01",  # 工序代码
                    "mtrl_code": move.product_id.default_code,  # 物料编码
                    "batch_no": ','.join(move.lot_ids.mapped('name')),  # 物料批次号
                    "qty": move.product_uom_qty,  # 发料数量
                })

            data_list = []
            for p in mrp_production_ids:
                top_production = self.top_production(p)
                try:
                    # 增加同步MES补救
                    if not top_production.s_mes_lock:
                        top_production.action_mes_production(login_list=[self.env.user.login])
                except Exception as e:
                    _logger.info(f'同步物料时自动同步mes失败 {e}')
                data_list.append({
                    "org_code": "0001",  # 组织编码
                    "mo_code": p.name,  # 工单编号, productions可能会有多个，目前只取最后一个，可能会出错
                    # 领料明细
                    "mtrl_list": mtrl_list
                })
            data = {
                "docType": "API_MO_STAT",  # 接口名称
                "updateType": "UPDATE",  # 更新类型
                "data": data_list
            }
            result = self.env['s.mes.upload'].upload_data(data)
            return result

    def _cron_mes_picking(self):
        """补-领料定时任务"""
        pickings = self.sudo().search([('picking_type_id.barcode', '=', 'WTT-CB'), ('state', '=', 'done'), ('s_mes_lock', '=', False)])
        mes_flag_time = self.env['s.api.config_parameter'].search([('s_key', '=', 'mes.flag_date')], limit=1).s_value
        pickings = pickings.filtered(lambda x: fields.Datetime.to_string(x.create_date) > mes_flag_time)
        for picking in pickings:
            try:
                _logger.info(f'补-领料定时任务，{picking.name}')
                result = picking.send_mes()
                if result.get('resultCode') != '0000':  # 请求失败
                    _logger.info(f'{len(pickings)}/补-领料定时任务，{picking.name}。同步失败')
                else:
                    _logger.info(f'{len(pickings)}/补-领料定时任务，{picking.name}。同步成功')
                    self.s_mes_lock = True
                    self.message_post(body=f"同步mes成功")
            except Exception as e:
                _logger.info(f'{len(pickings)}/补-领料定时任务，{picking.name}。同步失败{str(e)}')

